/*!	brief The Entity class is the "base" class of the TrollJS API. 
 *  Every object in the scene will only have an existence if they are attached
 * to an Entity Object 
 * 
 * 	An Entity object is, for now, defined by a mesh, a position and rotation
 */
Entity	=	function ( transform )
{
	/************************************
	/*			Properties				
	/************************************/
	
		this.m_Name;         /*!< Name of the Entity Object          */
		this.m_Transform;
		
		this.m_Father;
		this.m_Childs	=	new Array();
		
		this.m_Behaviours		=	new Array();	/*!< Behaviours attached to the current Entity		*/
		
		this.m_Transform;   	/*!< The Transform object is used to determine the Entity position and rotation in Space	*/
		
		this.m_View;		/*!< View linked to current Mesh		*/
		this.m_Mesh;        /*!< Mesh linked to the Entity object 	*/
		
		this.m_GLSLProgram;  		/*!< Id of a valid GLSL program compiled            */
		
		
		
		this.m_IsViewAttached;		/*!< Allow the Entity to know if a View is currently attached to it	*/
		
		
		
		//	Used for the textured attached to the current mesh entity
		
		this.m_OffsetX=0.0;
		this.m_OffsetY=1.0;
		
		this.m_ScaleX=1.0;
		this.m_ScaleY=1.0;
}

    /********************************
    /*          Members             
    /********************************/

        /********************************
        /*          Methods		        
        /********************************/
		
			Entity.prototype.SetModelMatrix	=	function()
			{
				var posMatrix		=	Matrix4.Translation(this.m_Transform.m_Position);
				var posInverse		=	Matrix4.TranslationInverse(this.m_Transform.m_Position);
				
				
				var rotMatrix		=	Quaternion.Euler(this.m_Transform.m_EulerAngles);
				var rotInverse		=	Quaternion.EulerInverse(this.m_Transform.m_EulerAngles);
				
				var scaleMatrix		=	Matrix4.Scale(this.m_Transform.m_Scale);
				var scaleInverse	=	Matrix4.ScaleInverse(this.m_Transform.m_Scale);
				
				this.m_Transform.m_LocalMatrix	=	posMatrix.MultMatrix(rotMatrix).MultMatrix(scaleMatrix);
				this.m_Transform.m_LocalInverse	=	posInverse.MultMatrix(scaleInverse).MultMatrix(rotInverse);
						
				if(this.m_Father!=undefined)
				{
					this.m_Transform.m_WorldMatrix	=	this.m_Father.m_Transform.m_WorldMatrix.MultMatrix(this.m_Transform.m_LocalMatrix);
					this.m_Transform.m_WorldInverse	=	this.m_Father.m_Transform.m_WorldInverse.MultMatrix(this.m_Transform.m_LocalInverse);
				}
				else
				{
					this.m_Transform.m_WorldMatrix	=	this.m_Transform.m_LocalMatrix;
					this.m_Transform.m_WorldInverse	=	this.m_Transform.m_LocalInverse;
				}
			}
			
			Entity.prototype.GetModelMatrix	=	function()
			{
				return this.m_Transform.m_WorldMatrix;
			}
			
			Entity.prototype.Update= function()
			{
				for (var i = 0 ; i< this.m_Behaviours.length; i++)
				{
					this.m_Behaviours[i].Update();
				}
				
				this.Display();
			}
			
			Entity.prototype.Display	=	function()
			{
                if(this.m_Mesh!=undefined)
                {
					this.SetModelMatrix();
                    this.m_GLSLProgram.Use();
					
					BufferObject.BindIBO();
					BufferObject.BindVBO();
					
					gl.activeTexture(gl.TEXTURE0);
					gl.bindTexture(gl.TEXTURE_2D, g_Image.m_Texture);
									
					gl.uniformMatrix4fv(this.m_GLSLProgram.m_Uniforms[0], false, new Float32Array( this.GetModelMatrix().AsArray()));
					gl.uniformMatrix4fv(this.m_GLSLProgram.m_Uniforms[1], false, new Float32Array(View.CurrentView.GetViewMatrix().AsArray()));
					gl.uniformMatrix4fv(this.m_GLSLProgram.m_Uniforms[2], false, new Float32Array(View.CurrentView.m_Projection.m_Matrix.AsArray()));
					
					gl.uniform1i(this.m_GLSLProgram.m_Uniforms[3], 0);
					gl.uniform1f(this.m_GLSLProgram.m_Uniforms[4], this.m_OffsetX);
					gl.uniform1f(this.m_GLSLProgram.m_Uniforms[5], this.m_OffsetY);
					gl.uniform1f(this.m_GLSLProgram.m_Uniforms[6], this.m_ScaleX);
					gl.uniform1f(this.m_GLSLProgram.m_Uniforms[7], this.m_ScaleY);
					
					this.m_Mesh.Display();
                }
			}
			
			Entity.prototype.AttachBehaviour		=	function(behaviour)
			{
				this.m_Behaviours.push(behaviour);
				behaviour.Attached(this);
			}
			
			Entity.prototype.AttachView	=	function(view)
			{
				this.m_View = view;
				this.m_View.m_Entity=this;
			
			}
			
			Entity.prototype.ReturnWorldFace	=	function()
			{
				
			}
			
	/********************************
    /*          Static             
    /********************************/

		/********************************
        /*          Properties		    
        /********************************/
			
            Entity.Last;           /*!< Last Entity inside the Entities container	*/
            Entity.First;          /*!< First Entity inside the Entities container	*/
			
            Entity.Entities= new Array();	/*!< Store all the Entites created	*/
			
		/********************************
        /*          Methods		        
        /********************************/
		
			Entity.Instantiate	=	function( transform )
			{
				var entity	=	new Entity();
				entity.m_Transform=transform;
				entity.m_GLSLProgram = GLSLProgram.Default;
				
				Entity.Entities.push(entity);
				return entity;
			}
			
			Entity.First = function()
			{
				return Entity.Entities[0];
			}

			Entity.Last = function()
			{
				return Entity.Entities[Entity.Entities.length-1];
			}
			
